
#include "stdafx.h"

TEST(socketTest, socket_in_inout)
{
    Header header(GetCurrentThreadId(), "socket");
    socket_in_inout socketIN(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    socket_in_inout socketOUT;

    std::vector<char> buffer;
    Serialize(header, socketIN, buffer);
        
    Deserialize deserialize(buffer);
    deserialize(socketOUT);

    EXPECT_EQ (header.TID_, deserialize.get_header().TID_);
    EXPECT_EQ (header.func_name_, deserialize.get_header().func_name_);

    EXPECT_EQ (socketIN.af_, socketOUT.af_);
    EXPECT_EQ (socketIN.type_, socketOUT.type_);
    EXPECT_EQ (socketIN.protocol_, socketOUT.protocol_);
}

//TEST(socketTest, socket_in_inout_NULL_parameters)
//{
//    
//}

TEST(socketTest, socket_out_inout)
{
    SOCKET sock = INVALID_SOCKET;
    
    Header header(GetCurrentThreadId(), "socket");
    socket_out_inout socketIN(sock, 7);
    socket_out_inout socketOUT;

    std::vector<char> buffer;
    Serialize(header, socketIN, buffer);
        
    Deserialize deserialize(buffer);
    deserialize(socketOUT);

    EXPECT_EQ (header.TID_, deserialize.get_header().TID_);
    EXPECT_EQ (header.func_name_, deserialize.get_header().func_name_);

    EXPECT_EQ (socketIN.ret_, socketOUT.ret_);
    EXPECT_EQ (socketIN.wsa_last_error_, socketOUT.wsa_last_error_);
}

//TEST(socketTest, socket_out_inout_NULL_parameters)
//{
//    
//}

bool CompareProtocolInfo (const WSAPROTOCOL_INFO& frst, const WSAPROTOCOL_INFO& snd)
{
    if (frst.dwServiceFlags1 != snd.dwServiceFlags1)
        return false;
    if (frst.dwServiceFlags2 != snd.dwServiceFlags2)
        return false;
    if (frst.dwServiceFlags3 != snd.dwServiceFlags3)
        return false;
    if (frst.dwServiceFlags4 != snd.dwServiceFlags4)
        return false;
    if (frst.dwProviderFlags != snd.dwProviderFlags)
        return false;
    if (frst.ProviderId.Data1 != snd.ProviderId.Data1)
        return false;
    if (frst.ProviderId.Data2 != snd.ProviderId.Data2)
        return false;
    if (frst.ProviderId.Data3 != snd.ProviderId.Data3)
        return false;
    if ( !memcmp(frst.ProviderId.Data4, snd.ProviderId.Data4, 8) )
        return false;
    if (frst.dwCatalogEntryId != snd.dwCatalogEntryId)
        return false;
    if (frst.ProtocolChain.ChainLen != snd.ProtocolChain.ChainLen)
        return false;
    if ( !memcmp(frst.ProtocolChain.ChainEntries, 
            snd.ProtocolChain.ChainEntries, sizeof(DWORD)* MAX_PROTOCOL_CHAIN) )
        return false;
    if (frst.iVersion != snd.iVersion)
        return false;
    if (frst.iAddressFamily != snd.iAddressFamily)
        return false;
    if (frst.iMaxSockAddr != snd.iMaxSockAddr)
        return false;
    if (frst.iMinSockAddr != snd.iMinSockAddr)
        return false;
    if (frst.iSocketType != snd.iSocketType)
        return false;
    if (frst.iProtocol != snd.iProtocol)
        return false;
    if (frst.iProtocolMaxOffset != snd.iProtocolMaxOffset)
        return false;
    if (frst.iNetworkByteOrder != snd.iNetworkByteOrder)
        return false;
    if (frst.iSecurityScheme != snd.iSecurityScheme)
        return false;
    if (frst.dwMessageSize != snd.dwMessageSize)
        return false;
    if (frst.dwProviderReserved != snd.dwProviderReserved)
        return false;
    if (frst.dwMessageSize != snd.dwMessageSize)
        return false;
    if ( !_tcsncmp (frst.szProtocol, snd.szProtocol, WSAPROTOCOL_LEN+1 ) )
        return false;
    return true;
}

TEST(WSASocketTest, WSASocket_in_inout)
{
    int i, nRet;
    WSAPROTOCOL_INFO *lpProtocolBuf = NULL;
    DWORD dwBufLen = 0;
    DWORD dwErr;
    BOOL bProtocolFound;
    
    // First, have WSAEnumProtocols() tell you how big a buffer you need
    nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);

    if (nRet != SOCKET_ERROR)
        printf("WSAEnumProtocols() does not return SOCKET_ERROR!\n");
    else if ((dwErr = WSAGetLastError()) != WSAENOBUFS)
        printf("WSAEnumProtocols() does not return WSAENOBUFS\n");
    else
    {
        lpProtocolBuf = (WSAPROTOCOL_INFO *)malloc(dwBufLen);
        if (lpProtocolBuf)
        {
            nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);
            if (nRet == SOCKET_ERROR)
                printf("WSAEnumProtocols() failed\n");
            else
            {
                // Loop through protocols, looking for the first service
                // provider that meets the matching criteria.
                // Originally FALSE, if found change to TRUE
                bProtocolFound = FALSE;
                for (i=0; i<nRet; i++)
                {
                    if ((lpProtocolBuf[i].iProtocol == IPPROTO_TCP) &&
                          ((XP1_QOS_SUPPORTED & lpProtocolBuf[i].dwServiceFlags1) ==
                                    XP1_QOS_SUPPORTED))
                    {
                        bProtocolFound = TRUE;
                        break;
                    }
                }
            }
        }
    }

    Header header(GetCurrentThreadId(), "WSASocket");
    WSASocket_in_inout WSASocketIN(
        FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
        &lpProtocolBuf[i], 0, WSA_FLAG_OVERLAPPED);
    WSASocket_in_inout WSASocketOUT;

    std::vector<char> buffer;
    Serialize(header, WSASocketIN, buffer);
        
    Deserialize deserialize(buffer);
    deserialize(WSASocketOUT);

    EXPECT_EQ (header.TID_, deserialize.get_header().TID_);
    EXPECT_EQ (header.func_name_, deserialize.get_header().func_name_);

    EXPECT_EQ (WSASocketIN.af_, WSASocketOUT.af_);
    EXPECT_EQ (WSASocketIN.type_, WSASocketOUT.type_);
    EXPECT_EQ (WSASocketIN.protocol_, WSASocketOUT.protocol_);
    if (WSASocketIN.lpProtocolInfo_ && WSASocketOUT.lpProtocolInfo_)
    {
        EXPECT_TRUE ( CompareProtocolInfo (*WSASocketIN.lpProtocolInfo_,
                                           *WSASocketOUT.lpProtocolInfo_) );
    } else {
        EXPECT_FALSE(WSASocketIN.lpProtocolInfo_);
        EXPECT_FALSE(WSASocketOUT.lpProtocolInfo_);
    }
    EXPECT_EQ (WSASocketIN.g_, WSASocketOUT.g_);
    EXPECT_EQ (WSASocketIN.dwFlags_, WSASocketOUT.dwFlags_);
}

TEST(socketTest, socket_in_inout_NULL_parameters)
{
    Header header(GetCurrentThreadId(), "WSASocket");
    WSASocket_in_inout WSASocketIN(AF_INET, SOCK_STREAM, IPPROTO_TCP,
        NULL, SG_UNCONSTRAINED_GROUP, WSA_FLAG_OVERLAPPED);
    WSASocket_in_inout WSASocketOUT;

    std::vector<char> buffer;
    Serialize(header, WSASocketIN, buffer);
        
    Deserialize deserialize(buffer);
    deserialize(WSASocketOUT);

    EXPECT_EQ (header.TID_, deserialize.get_header().TID_);
    EXPECT_EQ (header.func_name_, deserialize.get_header().func_name_);

    EXPECT_EQ (WSASocketIN.af_, WSASocketOUT.af_);
    EXPECT_EQ (WSASocketIN.type_, WSASocketOUT.type_);
    EXPECT_EQ (WSASocketIN.protocol_, WSASocketOUT.protocol_);
    if (WSASocketIN.lpProtocolInfo_ && WSASocketOUT.lpProtocolInfo_)
    {
        EXPECT_TRUE ( CompareProtocolInfo (*WSASocketIN.lpProtocolInfo_,
                                           *WSASocketOUT.lpProtocolInfo_) );
    } else {
        EXPECT_FALSE(WSASocketIN.lpProtocolInfo_);
        EXPECT_FALSE(WSASocketOUT.lpProtocolInfo_);
    }
    EXPECT_EQ (WSASocketIN.g_, WSASocketOUT.g_);
    EXPECT_EQ (WSASocketIN.dwFlags_, WSASocketOUT.dwFlags_);
}
